var common = angular.module('common', []);

common.directive("ngDtGrid", function () {
    return {
        /* template : "<div id='toolbar'></div>", //not a good impl */
        link: function (scope, element, attrs, ctrl) {
            $.post('/displayData/' + attrs.id, {}, function (data) {
                if (!!data._id) {
                    scope.metaData = data;
                    scope.data = [];
                    scope.init = true;
                    /**
                     * init data grid
                     * */
                    var dtGridColumns = [];

                    $.each(data.columns, function (obj) {
                        if(data.columns[obj].isDisplay) {
                            dtGridColumns.push({
                                id: data.columns[obj].columnName,
                                title: data.columns[obj].displayName,
                                type: data.columns[obj].dataType == "date" ? data.columns[obj].dataType : "string",
                                columnClass: 'text-center'
                            });
                        }
                    });

                    var dtGridOption = {
                        lang: 'zh-cn',
                        ajaxLoad: false,
                        datas: scope.data,
                        columns: dtGridColumns,
                        gridContainer: data._id,
                        toolbarContainer: data._id + "Toolbar",
                        pageSize: 20,
                        pageSizeLimit: [10, 20, 50]
                    };

                    scope.grid = $.fn.DtGrid.init(dtGridOption);
                    scope.grid.refresh();

                    $("#search-" + data._id).click(function () {
                        var criteria = {};
                        $.each(data.columns, function (col) {
                            if (data.columns[col].searchable) {
                                var fieldVal = null;
                                var fieldType = data.columns[col].dataType;
                                var colName = data.columns[col].columnName;
                                if (fieldType == 'date') {
                                    var dateFrom = $("#" + data.columns[col].columnName + "From").val();
                                    var dateTo = $("#" + data.columns[col].columnName + "To").val();
                                    criteria[colName] = {};
                                    if (dateFrom.length != 0) criteria[colName].$gt = new Date(dateFrom).getTime();
                                    if (dateTo.length != 0) criteria[colName].$lt = new Date(dateTo).getTime();
                                } else if (fieldType instanceof Object) {
                                    fieldVal = $("#" + data.columns[col].columnName).val();
                                    if (fieldType.multiSelect) {
                                        //todo append $or options to $and property
                                        if (fieldVal.length != 0)
                                            criteria[colName] = fieldVal;
                                    } else {
                                        if (fieldVal.length != 0)
                                            criteria[colName] = fieldVal;
                                    }
                                } else {
                                    fieldVal = $("#" + data.columns[col].columnName).val().replace(/\s+/, "");
                                    if (fieldType == 'array') {
                                        if (fieldVal.split(/[，|,|；|;]/).length != 0) {
                                            var optionsObj = [];
                                            var tempArray = fieldVal.split(/[，|,|；|;]/);
                                            for (var i = 0; i < tempArray.length; i++) {
                                                if (tempArray[i].trim().length != 0) {
                                                    var tempObj = {};
                                                    tempObj[colName] = tempArray[i];
                                                    optionsObj.push(tempObj);
                                                }
                                            }
                                            if (!criteria.$and) {
                                                criteria.$and = [];
                                            }
                                            if (optionsObj.length != 0)
                                                criteria.$and.push({$or: JSON.stringify(optionsObj)});
                                        }
                                    } else {
                                        if (fieldVal.length != 0)
                                            criteria[colName] = fieldVal;
                                    }
                                }
                            }
                        });
                        $.get("/collection/" + data._id,
                            {where: criteria, option: {page: [0, 20]}},
                            function (data) {
                                if (data instanceof Array) {
                                    scope.grid.exhibitDatas = data;
                                    scope.grid.reload.apply(scope.grid);
                                } else {
                                    //todo toast
                                    alert(data);
                                }
                            }
                        );
                    });


                }
            });
        }
    }
});


common.directive("easySelect", function () {
    return {
        link: function (scope, element, attrs) {
            var ngModel = $(element).attr("ng-model");
            if(!ngModel || ngModel.length == 0) {
                ngModel = "defaultSelectModel";
            }
            var status = false; //toggle boolean
            var valueMap = "";
            var options = $(element).children();
            $(element).attr("style", "padding:0");

            //hide original options
            $.each(options, function (opt) {
                $(options[opt]).attr("style", "display:none");
            });

            //build ul
            var html = "<div id='" + attrs.id + "-root' style='width:100%;position: relative;left:-1px'>" +
                "<p id='display-"+attrs.id + "' style='padding:6px 12px "+ ((attrs.multiple != undefined)?"4px":"7px")+
                " 12px;margin:0;border:none;width:95%;margin-left:2px;background-color: transparent'>" +
                "<span style='display: inline-block;padding-bottom: 3px'>&nbsp;</span></p>" +  //this is a dummy span
                "<ul id='" + attrs.id +
                "-container' class='list-group easy-select-container' style='display:none'>"; //options' container

            if(attrs.multiple != undefined) {
                $.each(options, function (opt) {
                    html += "<li value='"+ $(options[opt]).val() +"' class='my-li-container list-group-item option-"+
                    attrs.id+ "'><div style='width:100%;display:inline;position: relative;left:-14px;'>" + $(options[opt]).html() +
                    "</div><span value='"+ $(options[opt]).val() +"' class='my-li-option glyphicon glyphicon-ok'></span></li>";
                });
            } else {
                $.each(options, function (opt) {
                    if($(options[opt]).attr("default") != undefined) {
                        scope[ngModel] = $(options[opt]).val();
                        valueMap = $(options[opt]).html();
                        html += "<li value='"+ $(options[opt]).val() +"' class='my-li-container list-group-item option-"+ attrs.id+ "'>"
                        + $(options[opt]).html() + "</li>";
                    } else {
                        html += "<li value='"+ $(options[opt]).val() +"' class='my-li-container list-group-item option-"+ attrs.id+ "'>"
                        + $(options[opt]).html() + "</li>";
                    }
                });
            }

            //if multiple, add button
            if (attrs.multiple != undefined) {
                html += "<li class='list-group-item ' for='ensure-li'><button class='btn btn-default'" +
                " for='ensure-btn' style='padding: 2px' >&nbsp;&nbsp;确定&nbsp;&nbsp;</button></li>";
            }

            //render ui
            html += "</ul></div>";
            $(element).append(html);

            $(".my-li-option").each(function(){
                $(this).fadeTo(0,0.01);
            });

            if(attrs.multiple == undefined)
                $($("#display-"+attrs.id).children()[0]).html(valueMap);

            //adjust width
            $("#" + attrs.id + "-root").width($("#" + attrs.id + "-root").width() + 2);

            //mouse leave event
            $(element).mouseleave(function(){
                $(".my-li-container").each(function(){
                    $(this).attr("style","");
                });
                if(status) {
                    $("#" + attrs.id + "-container").attr("style", "display:none");
                    status = !status;
                }
            });

            //multiple select seems complex
            if (attrs.multiple != undefined) {
                //click event
                $(element).click(function (e) {
                    //if click on tags, remove it
                    if($(e.target).attr("for") == "option-tag") {
                        // change val and digest change item in angular
                        scope[ngModel] = $(element).val().replace($(e.target).attr("value"),"").replace(/;+/,";").replace(/^;/,"");
                        $(element).val(scope[ngModel]);
                        scope.$digest();
                        $(".my-li-option").each(function(){
                            if($(this).attr("value") == $(e.target).attr("value")) {
                                $(this).css("opacity","0.01");
                            }
                        });
                        $(e.target).remove();
                    } else if($(this).attr("for") != 'ensure-li') {
                        //toggle ul
                        $("#" + attrs.id + "-container").attr("style", status ? "display:none" : "");
                        status = !status;
                    }
                });

                $(".option-"+attrs.id).each(function(){
                    $(this).on('click',function(){
                        var selectValue = $(element).val();
                        var currentValue = $(this).attr("value");
                        var selected = false;
                        //if option is selected ,remove it
                        var temp = selectValue.split(";");
                        $.each(temp,function(obj){
                            if(temp[obj].indexOf(currentValue) != -1) {
                                selected = true;
                            }
                        })
                        if(selected) {
                            $($(this).children()[1]).fadeTo(300,0.01);
                            scope[ngModel] = $(element).val().replace(currentValue,"").replace(/;{2}/,";").replace(/^;/,"");
                            $(element).val(scope[ngModel]);
                            scope.$digest();
                            $("#display-"+attrs.id + " span").each(function(){
                                if($(this).attr("value") == currentValue) {
                                   $(this).remove();
                               }
                            });
                        } else {
                            //add option to val() and ui
                            $($(this).children()[1]).fadeTo(300,1);
                            scope[ngModel] = ($(element).val()+";"+currentValue).replace(/;{2}/,";").replace(/^;/,"");
                            $(element).val(scope[ngModel]);
                            scope.$digest();
                            $("#display-"+attrs.id).append(
                                "<span for='option-tag' value='"+ $(this).attr("value") +"' class='p-option-tag'>"
                                +$(this).children()[0].innerHTML+ "</span>");
                        }
                        status = !status; // prevent bubble
                    });

                    //control background
                    $(this).mouseenter(function(){
                        $(".my-li-container").each(function(){
                            $(this).attr("style","");
                        });
                        $(this).attr("style","background-color:#eee");
                    });
                });
            } else {
                $(".option-"+attrs.id).each(function(){
                    $(this).mouseenter(function(){
                        $(".my-li-container").each(function(){
                            $(this).attr("style","");
                        });
                        $(this).attr("style","background-color:#eee");
                    });
                });
                //single select ,just add value and remove ul
                $(element).click(function () {
                    $("#" + attrs.id + "-container").attr("style", status ? "display:none" : "");
                    status = !status;
                });

                $(".option-"+attrs.id).each(function(){
                    $(this).on('click',function(){
                        scope[ngModel] = $(this).attr("value");
                        $(element).val(scope[ngModel]);
                        scope.$digest();
                        $("#display-"+attrs.id).html("<span style='display: inline'>&nbsp;</span><span>"+ $(this).html()+"</span>");
                    });
                });
            }
        }
    }
});

common.directive("datetimepicker",function(){
    return {
        restrict: "EA",
        require : "ngModel",
        link: function (scope, element, attrs, ctrl) {
            var unregister = scope.$watch(function(){
                if(new Date(ctrl.$modelValue).valueOf() != 0) {
                    $(element).append("<input id='date-"+attrs.dateid+"' style='border:none' value='"+ctrl.$modelValue+"'>");
                } else {
                    $(element).append("<input id='date-"+attrs.dateid+"' style='border:none'>");
                }

                element.on('change', function() {
                    scope.$apply(function() {
                        ctrl.$setViewValue(new Date($("#date-"+attrs.dateid).val()).valueOf());
                    });
                });

                element.on('click',function(){
                    $("#date-"+attrs.dateid).datetimepicker({
                        format : attrs.format || 'Y/m/d h:i',
                        onClose : function(){
                            element.change();
                        }
                    });
                });

                element.click();

                return ctrl.$modelValue;
            }, initialize);

            function initialize(value){
                ctrl.$setViewValue(value);
                unregister();
            }
        }
    }
});

common.service("commonService",function(){
    this.htmlencode = function(s){
        var div = document.createElement('div');
        div.appendChild(document.createTextNode(s));
        return div.innerHTML;
    };
    this.htmldecode = function(s){
        var div = document.createElement('div');
        div.innerHTML = s;
        return div.innerText || div.textContent;
    };
    this.uuid = function () {
        return 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
            return v.toString(16);
        });
    };
    return this;
});